package com.stu.day17;

/**
 *  可见性:
 *  线程之间是隔离的 - 不同的线程之间是无法直接传递/访问这个自己工作内存中的变量的.必须通过主存
 *  线程中符合特定条件的时候,它会将本地工作内存中的数据刷回到主存.
 * @author zy
 * @date 2025/2/17 14:54
 */
public class VisibilityDemo {
    //private int x = 0;
    //4.保证可见性 - 强制每次都是从主存中去获取这个变量.
    private volatile int x = 0;

    //负责读
    public void read(){
        while(x!=5){
            //让读线程强制从主存中再次重新拉取

            //线程何时要从主存中重新拉变量的副本
            //1. 当前线程空闲的时候
//            try {
//                //sleep的背后是当前线程让出cpu时间片, 就会从主存中重新拉取这个x
//                Thread.sleep(1000);
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }

            //2. 遇到io操作
//            try {
//                new FileInputStream("src/tech/aistar/day16/GcDemo.java");
//            } catch (FileNotFoundException e) {
//                throw new RuntimeException(e);
//            }

            //3. 获取锁 - 当前获得锁的资源的线程会先清空本地缓存.
            //System.out.println();
//            synchronized (VisibilityDemo.class){
//
//            }
        }
        if(x==5){
            System.out.println("read...");
        }
    }

    //负责写
    public void write(){
        x = 5;
    }
}
class VisibilityDemoTest{
    public static void main(String[] args) {
        //仅仅创建一个对象的目的是为了让读线程和写线程共享数据
        VisibilityDemo v = new VisibilityDemo();

        Thread read = new Thread(()->{
            v.read();
        });
        Thread write = new Thread(()->{
            v.write();
        });
        //先读后写
        read.start();

        //是为了必须先执行read线程,再执行写write线程
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        //写线程一定在某个时刻将x=5值刷回到主存的.
        write.start();
    }
}
